package com.wingice.utils.file;

import com.wingice.exception.BusinessException;
import com.wingice.system.constant.FileConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 文件上传工具类
 */
@Slf4j
public class FileUtil {

    public static final Map<String, Integer> FILE_TYPE_MAP = new HashMap<>(16);

    static {
        //图片类
        FILE_TYPE_MAP.put("jpg", FileConstants.FILE_PIC);
        FILE_TYPE_MAP.put("jpeg", FileConstants.FILE_PIC);
        FILE_TYPE_MAP.put("png", FileConstants.FILE_PIC);
        FILE_TYPE_MAP.put("gif", FileConstants.FILE_PIC);
        FILE_TYPE_MAP.put("tif", FileConstants.FILE_PIC);
        FILE_TYPE_MAP.put("bmp", FileConstants.FILE_PIC);
        FILE_TYPE_MAP.put("dwg", FileConstants.FILE_PIC);
        FILE_TYPE_MAP.put("psd", FileConstants.FILE_PIC);

        //文件类
        FILE_TYPE_MAP.put("rtf", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("xml", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("html", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("css", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("js", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("eml", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("dbx", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("pst", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("doc", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("docx", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("xls", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("xlsx", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("csv", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("vsd", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("mdb", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("wps", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("ps", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("pdf", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("rar", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("zip", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("7z", FileConstants.FILE_DOC);
        FILE_TYPE_MAP.put("tar", FileConstants.FILE_DOC);

        //视频类
        FILE_TYPE_MAP.put("avi", FileConstants.FILE_VIDEO);
        FILE_TYPE_MAP.put("ram", FileConstants.FILE_VIDEO);
        FILE_TYPE_MAP.put("rm", FileConstants.FILE_VIDEO);
        FILE_TYPE_MAP.put("mpg", FileConstants.FILE_VIDEO);
        FILE_TYPE_MAP.put("mov", FileConstants.FILE_VIDEO);
        FILE_TYPE_MAP.put("asf", FileConstants.FILE_VIDEO);
        FILE_TYPE_MAP.put("mp4", FileConstants.FILE_VIDEO);
        FILE_TYPE_MAP.put("flv", FileConstants.FILE_VIDEO);
        FILE_TYPE_MAP.put("mid", FileConstants.FILE_VIDEO);

        //音乐类
        FILE_TYPE_MAP.put("wav", FileConstants.FILE_AUDIO);
        FILE_TYPE_MAP.put("mp3", FileConstants.FILE_AUDIO);

    }

    /**
     * 获得文件后缀
     *
     * @param fileName 文件全名称 demo.jpg
     * @return jpg
     * @date 2021/4/6 15:09
     */
    public static Integer getFileType(String fileName) {
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
        return FILE_TYPE_MAP.get(suffix);
    }

    /**
     * 文件山川校验 指定文件类别 默认大小
     * 图片类:默认5M
     * 文档类:默认10M
     * 视频类:默认100M
     * 音乐类:默认20M
     *
     * @param file             待校验文件
     * @param validateTypeList 文件类型枚举集合
     * @date 2021/4/6 15:34
     */
    public static void validateFile(MultipartFile file, List<Integer> validateTypeList) {
        Integer fileType = getFileType(Objects.requireNonNull(file.getOriginalFilename()).toLowerCase());
        if (fileType == null || StringUtils.isBlank(fileType.toString())) {
            throw new BusinessException("暂时不支持该类型文件！");
        }
        // 校验自定义fileType
        boolean fileTypeFlag = false;
        for (Integer type : validateTypeList) {
            if (type.equals(fileType)) {
                fileTypeFlag = true;
                break;
            }
        }
        if (!fileTypeFlag) {
            throw new BusinessException("暂时不支持该类型文件！");
        }
        // 校验文件大小
        // 图片类:默认5M 文档类:默认10M 视频类:默认100M 音乐类:默认20M
        for (Integer type : validateTypeList) {
            // 图片类
            if (FileConstants.FILE_PIC.equals(type) && FileConstants.FILE_PIC.equals(fileType)) {
                if (file.getSize() > FileConstants.SIZE_5_M) {
                    throw new BusinessException("上传的文件过大，请重新上传！");
                }
            }
            if (FileConstants.FILE_DOC.equals(type) && FileConstants.FILE_DOC.equals(fileType)) {
                if (file.getSize() > FileConstants.SIZE_10_M) {
                    throw new BusinessException("上传的文件过大，请重新上传！");
                }
            }
            if (FileConstants.FILE_VIDEO.equals(type) && FileConstants.FILE_VIDEO.equals(fileType)) {
                if (file.getSize() > FileConstants.SIZE_100_M) {
                    throw new BusinessException("上传的文件过大，请重新上传！");
                }
            }
            if (FileConstants.FILE_AUDIO.equals(type) && FileConstants.FILE_AUDIO.equals(fileType)) {
                if (file.getSize() > FileConstants.SIZE_20_M) {
                    throw new BusinessException("上传的文件过大，请重新上传！");
                }
            }
        }
    }

    /**
     * 文件山川校验 指定文件类别 指定大小
     * 1 - 10l
     * key: 文件类型
     * value: 文件大小
     *
     * @param file            待校验文件
     * @param fileTypeSizeMap 文件类型大小map
     * @date 2021/4/6 15:34
     */
    public static void validateFile(MultipartFile file, Map<Integer, Long> fileTypeSizeMap) {
        Integer fileType = getFileType(Objects.requireNonNull(file.getOriginalFilename()).toLowerCase());
        if (fileType == null || StringUtils.isBlank(fileType.toString())) {
            throw new BusinessException("暂时不支持该类型文件！");
        }
        // 校验自定义fileType
        boolean fileTypeFlag = false;
        for (Map.Entry<Integer, Long> entry : fileTypeSizeMap.entrySet()) {
            if (entry.getKey().equals(fileType)) {
                fileTypeFlag = true;
                break;
            }
        }
        if (!fileTypeFlag) {
            throw new BusinessException("暂时不支持该类型文件！");
        }
        for (Map.Entry<Integer, Long> entry : fileTypeSizeMap.entrySet()) {
            // 图片类
            if (FileConstants.FILE_PIC.equals(entry.getKey()) && FileConstants.FILE_PIC.equals(fileType)) {
                if (file.getSize() > entry.getValue()) {
                    throw new BusinessException("上传的文件过大，请重新上传！");
                }
            }
            if (FileConstants.FILE_DOC.equals(entry.getKey()) && FileConstants.FILE_DOC.equals(fileType)) {
                if (file.getSize() > entry.getValue()) {
                    throw new BusinessException("上传的文件过大，请重新上传！");
                }
            }
            if (FileConstants.FILE_VIDEO.equals(entry.getKey()) && FileConstants.FILE_VIDEO.equals(fileType)) {
                if (file.getSize() > entry.getValue()) {
                    throw new BusinessException("上传的文件过大，请重新上传！");
                }
            }
            if (FileConstants.FILE_AUDIO.equals(entry.getKey()) && FileConstants.FILE_AUDIO.equals(fileType)) {
                if (file.getSize() > entry.getValue()) {
                    throw new BusinessException("上传的文件过大，请重新上传！");
                }
            }
        }
    }

    /**
     * 删除单个文件
     *
     * @param fileName 要删除的文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                log.info("删除单个文件" + fileName + "成功！");
                return true;
            } else {
                log.info("删除单个文件" + fileName + "失败！");
                return false;
            }
        } else {
            log.info("删除单个文件失败：" + fileName + "不存在！");
            return false;
        }
    }

}
